package modelovectorial.core;

import modelovectorial.DocumentoPDF;
import modelovectorial.SearchResultStats;
import modelovectorial.persistencia.SearchResultDB;
import soporte.web.Pagination;
import utn.frc.tsb.utils.ValerioFritelli.HashTable.HashList;
import utn.frc.tsb.utils.ValerioFritelli.SimpleList.SimpleList;
import utn.frc.tsb.utils.ValerioFritelli.SortMethods.Ordenamiento;

/**
 * @project DLC Final / UTN FRC 2013
 * @date Febrero de 2013
 *
 * @author Gonzalo Arribere
 * @author Gustavo Morales
 * @author Pablo Moreno
 *
 * Esta clase representa un objeto que contendra todos los elementos necesarios
 * para mostrar en una pagina los resultados obtenidos a partir de una consulta
 * realizada por un usuario.
 */
public class SearchResult {

    // Arreglo con los documentos relevantes
    private DocumentoPDF[] mDocument;
    // Cantidad de documentos que fueron seleccionados por el motor para ser mostrados
    private int mResultSize;
    // Es la consulta realizada por el usuario sin ningun cambio previo
    private String mRealQuery;
    // Es la consulta realizada por el usuario sin signos de puntuacion y stop words
    private SimpleList mQuery;
    // Objeto Pagination que contendra todos los elementos necesarios para mostrar los resultados y las paginas en el navegador
    private Pagination mPagination;
    // Objeto que contendra todos los valores relacionados a estadisticas tales como cantidad de resultados, paginas, tiempos de ejecucion, etc.
    private SearchResultStats mStats;

    /**
     * Constructor por parametros que inicializa los atributos de la clase.
     *
     * @param pQuery
     * @param pRealQuery
     */
    public SearchResult(SimpleList pQuery, String pRealQuery) {
        mStats = new SearchResultStats();
        mStats.setQuery(pRealQuery);
        mStats.takeInitTime();

        if (!pQuery.isEmpty()) {
            mDocument = SearchResultDB.executeQuery(pQuery);
            mRealQuery = pRealQuery;
            mQuery = pQuery;

            if (mDocument == null) {
                mResultSize = 0;
            } else {
                mResultSize = mDocument.length;
            }
        } else {
            mResultSize = 0;
        }
    }

    public SimpleList getProcessedQuery() {
        return mQuery;
    }

    public String getRealQuery() {
        return mRealQuery;
    }

    /**
     * Resuelve el modelo vectorial y deja solo los resultados relevantes para
     * la busqueda.
     */
    public void compute() {
        if (mResultSize == 0) {
            return;
        }

        int totalDocuments = DocumentoPDF.getTotalDocuments();

        int len = mDocument.length;

        for (int i = 0; i < len; i++) {
            mDocument[i].computeTFIDF(totalDocuments);
        }

        Ordenamiento.quickSort(mDocument);

        for (int i = len - 1; i >= 0; i--) {
            if (mDocument[i].getTfidf() >= SearchEngine.MIN_ACEPTABLE_VALUE) {
                mResultSize = i + 1;
                break;
            }
        }

        DocumentoPDF realDocuments[] = new DocumentoPDF[mResultSize];
        System.arraycopy(mDocument, 0, realDocuments, 0, mResultSize);
        mDocument = realDocuments;

        mStats.setMaxPages(Pagination.calculateMaxPages(mDocument.length));
        mStats.setTotalResults(mDocument.length);
    }

    public int results() {
        return mResultSize;
    }

    public DocumentoPDF getDocumentAt(int pIndex) {
        return mDocument[pIndex];
    }

    /**
     * Lee los documentos de la base de datos para que estos busquen sus
     * terminos.
     *
     * @param pPageNumber numero de pagina.
     */
    public void fillDocuments(int pPageNumber) {
        if (mResultSize == 0) {
            mStats.takeEndTime();
            return;
        }

        mPagination = new Pagination(pPageNumber);
        mPagination.buildPagination(mResultSize);
        mPagination.fixEndIndex(mDocument.length);

        HashList documents = DocumentoPDF.getDocuments(mDocument, mPagination);

        documents = DocumentoPDF.getDocumentsMinIndex(documents, mPagination, mQuery);

        DocumentoPDF[] documentsResult = new DocumentoPDF[mPagination.getEndIndex() - mPagination.getInitIndex() + 1];

        int j = 0;
        for (int i = mPagination.getInitIndex(); i <= mPagination.getEndIndex(); i++) {
            mDocument[i].copy((DocumentoPDF) documents.get(mDocument[i]), false);
            mDocument[i].fillTerms(true);
            documentsResult[j] = mDocument[i];
            j++;
        }
        mDocument = documentsResult;
        mResultSize = j;

        mStats.takeEndTime();
        mStats.setSelectedPage(pPageNumber);
    }

    public DocumentoPDF[] getDocuments() {
        return mDocument;
    }

    public SearchResultStats getStats() {
        return mStats;
    }
}